/**
 Application.h
 \file Declaration of class Application
 
 \author Thomas Burton
 \date 12/6/11
 \copyright 2011 BNL
 */

#ifndef _Application_H_
#define _Application_H_

#include <ostream>

#ifndef __CINT__ // ROOT CINT cannot handle BOOST headers
#include <boost/scoped_ptr.hpp>
#endif

#include <TFile.h>
#include <TRandom3.h>
#include <TStopwatch.h>

#include "tppmc/Configuration.h"
#include "tppmc/Distributions.h"
#include "tppmc/Pythia6.h"

class TTree;

namespace tppmc {
   
   class Configuration;
   class Event;
   
   /**
    The main TPPMC application.
    */
   class Application {
      
   public:
      
      /** Default constructor */
      Application();
      
      /**
       Constructor.
       Initialise the application for a particular configuration.
       */
      Application(Configuration&);
      
      /** Destructor */
      virtual ~Application();
      
      /** Initialise the application for a particular configuration */
      virtual bool Initialise(Configuration&);
      
      /** Generate and process a single event */
      virtual bool ProcessEvent();
      
      /** End the application, writing output */
      virtual bool Close();
      
      /**
       Process n events.
       If n < 1, the number of events is the number in the Configuration used to
       Initialise the Application.
       */
      virtual bool EventLoop(int n);
      
      /** Print the application splash screen to an output stream */
      virtual void Splash(std::ostream& = std::cout) const;
      
      /** Returns the current onfiguration of the application */
      virtual Configuration& Config();
      
   protected:
      
      /** The application is not to be copied */
      Application(const Application&) { }
      
      /** The application is not to be copied */
      Application& operator=(const Application&) { return *this; }
      
      Configuration mConfig; ///< Configuration determining how we run
      
#ifndef __CINT__
      boost::scoped_ptr<TFile> mQaFile; ///< Output file for QA figures
      
      boost::scoped_ptr<TFile> mTreeFile; ///< Output file for event tree

//      boost::scoped_ptr<Pythia6> mGenerator; ///< Event generator
      
      boost::scoped_ptr<Distributions> mPdfs; ///< Distribution functions,
                                              ///< PDFs and fragmentation
      
      boost::scoped_ptr<TRandom> mRandom; ///< The application's random
                                          ///< number generator
      
      boost::scoped_ptr<TStopwatch> mTimer; ///< Times running
#endif
      
      TTree* mTree; ///< Output event tree
      Event* mEvent; ///< Event buffer for output tree.
                     ///< A bare pointer because TTree doesn't seem to play
                     ///< nicely with smart pointers.
      
      static const unsigned smVersionMajor = 1;
      static const unsigned smVersionMinor = 2;
      
      ClassDef(Application, 1)
   };
   
   inline Configuration& Application::Config() { return mConfig; }

} // namespace tppmc

#endif
